package com.weifly.weistock.record.option.impl;

import com.weifly.weistock.core.util.WeistockUtils;
import com.weifly.weistock.core.util.visitor.PreviousVisitor;
import com.weifly.weistock.record.RecordUtils;
import com.weifly.weistock.record.bo.MergeRecordResult;
import com.weifly.weistock.record.option.*;
import com.weifly.weistock.record.option.domain.*;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
 * 交易记录管理服务实现
 *
 * @author weifly
 * @since 2019/11/18
 */
public class OptionMonitorServiceImpl implements OptionMonitorService {

    private SortedMap<String, OptionYearDto> yearMap = new TreeMap<>(); // key有序的map

    private OptionStoreService optionStoreService;

    public void setOptionStoreService(OptionStoreService optionStoreService) {
        this.optionStoreService = optionStoreService;
    }

    @Override
    public void updateYearList(List<OptionYearDto> yearList) {
        this.yearMap.clear();
        for(OptionYearDto yearDto : yearList){
            this.yearMap.put(yearDto.getYear(), yearDto);
        }
    }

    @Override
    public MergeRecordResult mergeRecordList(List<OptionRecordDto> recordList) {
        MergeRecordResult result = new MergeRecordResult();
        if(recordList==null || recordList.isEmpty()){
            return result;
        }

        Map<String, OptionYearDto> modifyYearMap = new TreeMap<>(); // 被修改的年记录
        Set<String> modifyContractSet = new HashSet<>(); // 被修改和合约集合
        result.setTotal(recordList.size());

        // 合并record到year
        for(OptionRecordDto recordDto : recordList){
            OptionUtils.checkEmpty(recordDto.getDate(), "发生日期不能为空");
            OptionUtils.checkEmpty(recordDto.getEntrustCode(), "委托编号不能为空");
            String recordYear = recordDto.getDate().substring(0, 4);
            OptionYearDto yearDto = this.findOrCreateYear(recordYear);
            OptionUtils.addRecordToYear(yearDto, recordDto, result);
            modifyYearMap.put(recordYear, yearDto);
            modifyContractSet.add(recordDto.getContractCode());
        }

        // 交易记录排序
        for(OptionYearDto yearDto : modifyYearMap.values()){
            RecordUtils.sortRecordList(yearDto.getRecordList());
        }

        // 写入存储
        for(OptionYearDto yearDto : modifyYearMap.values()){
            this.optionStoreService.saveOptionYear(yearDto);
        }

        // 计算合约盈亏
        CalcContractRequest calcRequest = new CalcContractRequest();
        calcRequest.setAll(false);
        calcRequest.setContractSet(modifyContractSet);
        this.calcContract(calcRequest);

        return result;
    }

    @Override
    public void calcContract(CalcContractRequest request) {
        Map<String, OptionYearDto> modifyYearMap = new TreeMap<>(); // 被修改的年记录
        Map<String, List<OptionRecordDto>> contractMap = new LinkedHashMap<>(); // 合约交易记录集合
        for(OptionYearDto yearDto : this.yearMap.values()){
            for(OptionRecordDto recordDto : yearDto.getRecordList()){
                if(request.isAll() || request.getContractSet().contains(recordDto.getContractCode())){
                    modifyYearMap.put(yearDto.getYear(), yearDto);
                    OptionUtils.addRecordToMap(contractMap, recordDto);
                }
            }
        }

        // 对于每个合约，计算盈亏
        for(List<OptionRecordDto> recordList : contractMap.values()){
            this.calcOneContract(recordList);
        }

        // 写入存储
        for(OptionYearDto yearDto : modifyYearMap.values()){
            this.optionStoreService.saveOptionYear(yearDto);
        }
    }

    public void calcOneContract(List<OptionRecordDto> recordList){
        OptionUtils.clearRecordPair(recordList);
        CalcContractContext calcCtx = new CalcContractContext();
        for(int i=0;i<recordList.size();i++){
            OptionRecordDto currRecord = recordList.get(i);
            // 处理平仓记录
            if(OptionUtils.isCloseRecord(currRecord)){
                calcCtx.initRecord(currRecord);
                for(int j=i-1;j>=0;j--){
                    OptionRecordDto preRecord = recordList.get(j);
                    calcCtx.buildPair(preRecord);
                    if(calcCtx.getCurrTradeNumber()<=0){
                        // 完成配对
                        break;
                    }
                }
                calcCtx.finishRecord();
            }
        }
    }

    @Override
    public List<OptionRecordDto> getRecordList(GetRecordRequest recordRequest) {
        int limit = recordRequest.getLimit();
        List<OptionRecordDto> recordList = new ArrayList<>();
        Iterator<OptionRecordDto> recordIter = new PreviousVisitor(this.yearMap.values());
        while(recordIter.hasNext()){
            OptionRecordDto recordDto = recordIter.next();
            if(!this.filterRecord(recordDto, recordRequest)){
                recordList.add(recordDto);
                if(recordList.size()>=limit){
                    break;
                }
            }
        }
        return recordList;
    }

    // 需要过滤的记录，则返回true
    private boolean filterRecord(OptionRecordDto recordDto, GetRecordRequest request){
        // 日期、时间、委托编号、买卖标志、合约编码过滤
        if(StringUtils.isNotBlank(request.getDate())
                && StringUtils.isNotBlank(request.getTime())
                && StringUtils.isNotBlank(request.getEntrust())
                && request.getOperationType()!=null
                && StringUtils.isNotBlank(request.getContractCode())){
            int dataCompare = recordDto.getDate().compareTo(request.getDate());
            // 判断date
            if(dataCompare>0){
                return true; // record date 大，需要过滤
            }else if(dataCompare<0){
                // record date 小，不需要过滤
            }else{
                // 判断time
                int timeCompare = recordDto.getTime().compareTo(request.getTime());
                if(timeCompare>0){
                    return true; // record time 大，需要过滤
                }else if(timeCompare<0){
                    // record time 小，不需要过滤
                }else{
                    // 判断entrustCode
                    int entrustCodeCompare = recordDto.getEntrustCode().compareTo(request.getEntrust());
                    if(entrustCodeCompare>0){
                        return true; // record entrustCode大，需要过滤
                    }else if(entrustCodeCompare<0){
                        // record entrustCode小，不需要过滤
                    }else{
                        // 判断买卖标志
                        int operationTypeCompare = recordDto.getOperationType().getCode().compareTo(request.getOperationType().getCode());
                        if(operationTypeCompare>0){
                            return true; // record operationType大，需要过滤
                        }else if(operationTypeCompare<0){
                            // record operationType小，不需要过滤
                        }else{
                            // 判断合约编码
                            int contractCodeCompare = recordDto.getContractCode().compareTo(request.getContractCode());
                            if(contractCodeCompare>=0){
                                return true; // record contractCode大，需要过滤
                            }else{
                                // record contractCode小，不需要过滤
                            }
                        }
                    }
                }
            }
        }

        // 合约编码过滤
        if(StringUtils.isNotBlank(request.getFilterContractCode())){
            if(!recordDto.getContractCode().equals(request.getFilterContractCode())){
                return true;
            }
        }

        // 配对情况过滤
        if(StringUtils.isNotBlank(request.getFilterPair())){
            if("yes".equals(request.getFilterPair())){ // 只需要已配对的记录
                if(recordDto.getPairList()==null || recordDto.getPairList().isEmpty()){
                    return true;
                }
            }else if("no".equals(request.getFilterPair())){ // 只需要未配对的记录
                if(OptionUtils.getNotPairNumber(recordDto)<=0){
                    return true;
                }
                // 不需要 行权指派
                if(OptionConst.BusinessName.NAME_9.equals(recordDto.getBusinessName())){
                    return true;
                }
            }
        }

        return false;
    }

    private OptionYearDto findOrCreateYear(String year){
        OptionYearDto yearDto = this.yearMap.get(year);
        if(yearDto==null){
            yearDto = new OptionYearDto();
            yearDto.setYear(year);
            this.yearMap.put(year, yearDto);
        }
        return yearDto;
    }

    @Override
    public OptionSummaryDto loadSummaryInfo() {
        double totalFeeService = 0;
        double totalDiffAmount = 0;
        double diffAmountUp = 0;
        double diffAmountDown = 0;
        Iterator<OptionRecordDto> recordIter = new OptionRecordVisitor(this.yearMap.values()).nextIter();
        while(recordIter.hasNext()){
            OptionRecordDto recordDto = recordIter.next();
            if(recordDto.getFeeService()!=null){
                totalFeeService = WeistockUtils.add(totalFeeService, recordDto.getFeeService());
            }
            if(recordDto.getDiffAmount()!=null){
                totalDiffAmount = WeistockUtils.add(totalDiffAmount, recordDto.getDiffAmount());
                if(recordDto.getDiffAmount()>=0){
                    diffAmountUp = WeistockUtils.add(diffAmountUp, recordDto.getDiffAmount());
                }else{
                    diffAmountDown = WeistockUtils.add(diffAmountDown, recordDto.getDiffAmount());
                }
            }
        }

        OptionSummaryDto summaryDto = new OptionSummaryDto();
        summaryDto.setFeeService(totalFeeService);
        summaryDto.setDiffAmount(totalDiffAmount);
        summaryDto.setDiffAmountUp(diffAmountUp);
        summaryDto.setDiffAmountDown(diffAmountDown);
        return summaryDto;
    }
}
